import pandas as pd
from os import listdir
from os.path import isfile, join
from io import StringIO
ClickHouse https://redash.trg.corp.mail.ru/queries/28482/source
interests_path = '/home/eka.volkova/TRG-91593_interests_statistics/interests_statistics/interests_all_targeting_id.csv' # все target_id
# interests_path = '/home/eka.volkova/TRG-90187_age_means/interests.csv' # target_id = 5
# Беру интересы со всеми target_id, если брать только target_id=5, то почти 74% интересов не заполнено
interests = pd.read_csv(interests_path)
interests.rename(columns={'value': 'interests', 'description': 'interest_name'}, inplace=True)
interests['interests'] = interests['interests'].astype('str')
interests.set_index('interests', inplace=True)
interests.info()
<class 'pandas.core.frame.DataFrame'> Index: 719 entries, 7354 to 10015 Data columns (total 1 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 interest_name 719 non-null object dtypes: object(1) memory usage: 11.2+ KB
interests.head()
| interest_name | |
|---|---|
| interests | |
| 7354 | Авто / Автовладельцы |
| 7358 | Мобильные устройства / Сотовые телефоны и гарн... |
| 7359 | Мобильные устройства / Планшеты и электронные ... |
| 7360 | Мобильные устройства / Ноутбуки и нетбуки |
| 7361 | Одежда, обувь и аксессуары / Женская одежда |
orig_data_path = '/home/eka.volkova/TRG-90187_age_means/orig_data/show_install/'
csv_files = [f for f in listdir(orig_data_path) if (isfile(join(orig_data_path, f)) and f.find('.csv') != -1)]
csv_files.sort()
csv_files
['show_install_20221107002350.csv', 'show_install_20221107022320.csv', 'show_install_20221107041600.csv', 'show_install_20221107062340.csv', 'show_install_20221107082340.csv', 'show_install_20221107102248.csv', 'show_install_20221107122410.csv', 'show_install_20221107142450.csv', 'show_install_20221107162310.csv', 'show_install_20221107182117.csv', 'show_install_20221107202430.csv', 'show_install_20221107222240.csv', 'show_install_20221108002400.csv', 'show_install_20221108022420.csv', 'show_install_20221108041910.csv', 'show_install_20221108062400.csv', 'show_install_20221108082440.csv', 'show_install_20221108101855.csv', 'show_install_20221108122930.csv', 'show_install_20221108142320.csv', 'show_install_20221108162250.csv', 'show_install_20221108182400.csv', 'show_install_20221108202240.csv', 'show_install_20221108222410.csv', 'show_install_20221109002450.csv', 'show_install_20221109022530.csv', 'show_install_20221109042030.csv', 'show_install_20221109062350.csv', 'show_install_20221109082440.csv', 'show_install_20221109102100.csv', 'show_install_20221109122400.csv', 'show_install_20221109142320.csv', 'show_install_20221109162410.csv', 'show_install_20221109182340.csv', 'show_install_20221109202150.csv', 'show_install_20221109222400.csv', 'show_install_20221110002300.csv', 'show_install_20221110022310.csv', 'show_install_20221110041720.csv', 'show_install_20221110062400.csv', 'show_install_20221110082300.csv', 'show_install_20221110102130.csv', 'show_install_20221110122420.csv', 'show_install_20221110142410.csv', 'show_install_20221110162250.csv', 'show_install_20221110182157.csv', 'show_install_20221110202510.csv', 'show_install_20221110222010.csv', 'show_install_20221111002330.csv', 'show_install_20221111022240.csv', 'show_install_20221111042400.csv', 'show_install_20221111062230.csv', 'show_install_20221111082130.csv', 'show_install_20221111102220.csv', 'show_install_20221111122410.csv', 'show_install_20221111142300.csv', 'show_install_20221111162400.csv', 'show_install_20221111182240.csv', 'show_install_20221111202200.csv', 'show_install_20221111222350.csv', 'show_install_20221112002350.csv', 'show_install_20221112022400.csv', 'show_install_20221112042000.csv', 'show_install_20221112062500.csv', 'show_install_20221112082250.csv', 'show_install_20221112101920.csv', 'show_install_20221112122520.csv', 'show_install_20221112142520.csv', 'show_install_20221112162150.csv', 'show_install_20221112182310.csv', 'show_install_20221112202230.csv', 'show_install_20221112222310.csv', 'show_install_20221113002410.csv', 'show_install_20221113022520.csv', 'show_install_20221113041630.csv', 'show_install_20221113062410.csv', 'show_install_20221113082430.csv', 'show_install_20221113101950.csv', 'show_install_20221113122320.csv', 'show_install_20221113142220.csv', 'show_install_20221113162340.csv', 'show_install_20221113182110.csv', 'show_install_20221113202100.csv', 'show_install_20221113221850.csv', 'show_install_20221114002400.csv', 'show_install_20221114022350.csv', 'show_install_20221114041840.csv', 'show_install_20221114062420.csv', 'show_install_20221114082308.csv', 'show_install_20221114102207.csv', 'show_install_20221114122310.csv', 'show_install_20221114142350.csv', 'show_install_20221114162340.csv', 'show_install_20221114182020.csv', 'show_install_20221114202400.csv', 'show_install_20221114222310.csv', 'show_install_20221115002520.csv', 'show_install_20221115022140.csv', 'show_install_20221115042030.csv', 'show_install_20221115062450.csv', 'show_install_20221115082320.csv', 'show_install_20221115102140.csv', 'show_install_20221115122340.csv', 'show_install_20221115142330.csv', 'show_install_20221115162220.csv', 'show_install_20221115182250.csv', 'show_install_20221115202230.csv', 'show_install_20221115222330.csv', 'show_install_20221116002410.csv', 'show_install_20221116022430.csv', 'show_install_20221116041610.csv', 'show_install_20221116061950.csv', 'show_install_20221116082240.csv', 'show_install_20221116101850.csv', 'show_install_20221116122330.csv', 'show_install_20221116142440.csv', 'show_install_20221116162340.csv', 'show_install_20221116182330.csv', 'show_install_20221116202340.csv', 'show_install_20221116222330.csv']
len(csv_files)
120
len([file for file in csv_files if file[19:21] in ('07')])
12
# show_install_20221107*.csv
show_install = \
pd.concat([pd.read_csv(f'{orig_data_path}{file}', sep=';') for file in [file for file in csv_files if file[19:21] in ('07')]], ignore_index=True)
show_install.shape
(159005975, 11)
show_install.replace(to_replace={'ev_type': 7}, value=1, inplace=True)
show_install['ev_type'].value_counts()
0 152731803 1 6274172 Name: ev_type, dtype: int64
show_install['ev_type'].value_counts().sum()
159005975
show_install.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 159005975 entries, 0 to 159005974 Data columns (total 11 columns): # Column Dtype --- ------ ----- 0 age float64 1 age_targetings int64 2 app int64 3 ev_type int64 4 has_interest int64 5 iab_app_category object 6 interests int64 7 matched_bits int64 8 rb_mobile_app_id int64 9 sex int64 10 timestamp int64 dtypes: float64(1), int64(9), object(1) memory usage: 13.0+ GB
show_install['interests'] = show_install['interests'].astype('str')
show_install = show_install.join(interests['interest_name'], on='interests')
show_install.fillna(value={'interest_name': 'Не определено'}, inplace=True)
show_install['interest_name'].value_counts()
CrossFire: Неактивные 3447333
Armored Warfare: Неактивные 3447333
Armored Warfare: Незарегистрированные 3447333
CrossFire: Незарегистрированные 3447333
Skyforge: Незарегистрированные 3447333
...
Бизнес / Юридическая поддержка 124
Пользователи сервисов такси 111
Образование / Средне-специальное 79
Образование / Высшее 79
Финансы / Игра на бирже / Бинарные опционы 2
Name: interest_name, Length: 489, dtype: int64
show_install[show_install['interest_name'].isna()].shape[0]
0
show_install.head()
| age | age_targetings | app | ev_type | has_interest | iab_app_category | interests | matched_bits | rb_mobile_app_id | sex | timestamp | interest_name | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 57.0 | 60 | 2825035 | 0 | 0 | 473 | 10248 | 0 | 2825035 | 2 | 1667769830 | Нет высшего образования |
| 1 | 57.0 | 60 | 2825035 | 0 | 0 | 473 | 12279 | 0 | 2825035 | 2 | 1667769830 | ArcheAge: Незарегистрированные |
| 2 | 57.0 | 60 | 2825035 | 0 | 0 | 473 | 12280 | 0 | 2825035 | 2 | 1667769830 | Armored Warfare: Незарегистрированные |
| 3 | 57.0 | 60 | 2825035 | 0 | 0 | 473 | 12281 | 0 | 2825035 | 2 | 1667769830 | CrossFire: Незарегистрированные |
| 4 | 57.0 | 60 | 2825035 | 0 | 0 | 473 | 12287 | 0 | 2825035 | 2 | 1667769830 | Skyforge: Незарегистрированные |
show_install_interests = show_install.copy()[['interest_name', 'ev_type']]
show_install_interests = show_install_interests.groupby(by='interest_name')['ev_type'].mean().rename('cr')
show_install_interests.sort_values(ascending=False, inplace=True)
show_install_interests.head()
interest_name Профессиональная область / Безопасность 0.062160 Финансы / Потребительские кредиты 0.059974 Финансы / Кредитные карты 0.059866 Финансы / Микрозаймы 0.059858 Отдел, подразделение / Обеспечение безопасности, охрана 0.059325 Name: cr, dtype: float64
# import plotly.express as px
import plotly.graph_objects as go
top = 30
df_bar = show_install_interests.head(top).sort_values().reset_index()
fig = \
go.Figure(
data=go.Bar(
x=df_bar['cr'], y=df_bar['interest_name'],
orientation='h'),
layout=go.Layout(
title='Топ интересов',
xaxis={'domain': [0.45, 1]},
yaxis={'anchor': 'free', 'position': 0, 'side': 'right'},
height=20*top)
)
fig.show()
show_install_app = show_install.copy()[['interest_name', 'ev_type', 'app']]
# Количество инсталлов по приложениям должно быть хотя бы от 5 и показов от 100
show_install_app = \
show_install_app.groupby(by='app').agg(
shows=pd.NamedAgg(column='ev_type', aggfunc='count'),
installs=pd.NamedAgg(column='ev_type', aggfunc='sum'),
cr=pd.NamedAgg(column='ev_type', aggfunc='mean')
).query('shows + installs >= 100 and installs >= 5')
show_install_app.sort_values(by=['cr', 'installs'], ascending=[False, False], inplace=True)
show_install_app.head()
| shows | installs | cr | |
|---|---|---|---|
| app | |||
| 10409400 | 529 | 529 | 1.0 |
| 10380882 | 458 | 458 | 1.0 |
| 10387842 | 324 | 324 | 1.0 |
| 10406911 | 315 | 315 | 1.0 |
| 5138847 | 290 | 290 | 1.0 |
show_install_app_interest = show_install.copy()[['interest_name', 'ev_type', 'app']]
show_install_app_interest = \
show_install_app_interest.groupby(by=['app', 'interest_name']).agg(
shows=pd.NamedAgg(column='ev_type', aggfunc='count'),
installs=pd.NamedAgg(column='ev_type', aggfunc='sum'),
cr=pd.NamedAgg(column='ev_type', aggfunc='mean')
)
show_install_app_interest.reset_index(level='interest_name', inplace=True)
show_install_app_interest.sort_values(by='cr', ascending=False, inplace=True)
show_install_app_interest.head()
| interest_name | shows | installs | cr | |
|---|---|---|---|---|
| app | ||||
| 9773251 | Досуг и развлечение / Знакомства | 1 | 1 | 1.0 |
| 10334664 | Средний | 2 | 2 | 1.0 |
| 4884033 | Телезрители | 1 | 1 | 1.0 |
| 10334664 | Холост | 2 | 2 | 1.0 |
| 4884033 | Холост | 1 | 1 | 1.0 |
# Выбираем Топ N приложений по CR
top_show_install_app = 100 # количество приложений
show_install_top_app_interest = show_install_app.head(top_show_install_app)
# Отбираем по уровню CR
# show_install_top_app_interest = show_install_app[show_install_app['cr'] == 1]
# Топ приложений с НЕ 100% CR
# show_install_top_app_interest = show_install_app[show_install_app['cr'] != 1].head(top_show_install_app)
show_install_top_app_interest = \
show_install_top_app_interest.iloc[:, :-4].\
join(show_install_app_interest, on='app').query('cr > 0.0')
show_install_top_app_interest.reset_index(inplace=True)
show_install_top_app_interest.head()
| app | interest_name | shows | installs | cr | |
|---|---|---|---|---|---|
| 0 | 10409400 | CrossFire: Неактивные | 11 | 11 | 1.0 |
| 1 | 10409400 | Armored Warfare: Незарегистрированные | 11 | 11 | 1.0 |
| 2 | 10409400 | Armored Warfare: Неактивные | 11 | 11 | 1.0 |
| 3 | 10409400 | ArcheAge: Незарегистрированные | 11 | 11 | 1.0 |
| 4 | 10409400 | CrossFire: Незарегистрированные | 11 | 11 | 1.0 |
top_interest=15 # Количество интересов в рамках одного приложения
show_install_top_app_interest = show_install_top_app_interest.groupby(by='app').head(top_interest)
show_install_top_app_interest.head()
| app | interest_name | shows | installs | cr | |
|---|---|---|---|---|---|
| 0 | 10409400 | CrossFire: Неактивные | 11 | 11 | 1.0 |
| 1 | 10409400 | Armored Warfare: Незарегистрированные | 11 | 11 | 1.0 |
| 2 | 10409400 | Armored Warfare: Неактивные | 11 | 11 | 1.0 |
| 3 | 10409400 | ArcheAge: Незарегистрированные | 11 | 11 | 1.0 |
| 4 | 10409400 | CrossFire: Незарегистрированные | 11 | 11 | 1.0 |
show_install_top_app_interest.shape
(1500, 5)
Получаем список приложений, которые есть в обучающей выборке и выгружаем их из ClichHouse https://redash.trg.corp.mail.ru/queries/28422/source
app_path = '/home/eka.volkova/TRG-91593_interests_statistics/interests_statistics/app.csv'
app = pd.read_csv(app_path)
app.rename(columns={'rb_mobile_app_id': 'app', 'title': 'app_name'}, inplace=True)
app.set_index('app', inplace=True)
app.head()
| app_name | category | |
|---|---|---|
| app | ||
| 10399771 | Честно деньги: на карту быстро | Финансы |
| 1514710 | Авиабилеты, отели и РЖД билеты | Путешествия |
| 9978066 | Кредо займы онлайн | Финансы |
| 9721050 | Робот Займер - Займы онлайн | Финансы |
| 14407 | Едадил: скидки в магазинах | Покупки |
show_install_top_app_interest = show_install_top_app_interest.join(app, on='app')
show_install_top_app_interest.head()
| app | interest_name | shows | installs | cr | app_name | category | |
|---|---|---|---|---|---|---|---|
| 0 | 10409400 | CrossFire: Неактивные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 1 | 10409400 | Armored Warfare: Незарегистрированные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 2 | 10409400 | Armored Warfare: Неактивные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 3 | 10409400 | ArcheAge: Незарегистрированные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 4 | 10409400 | CrossFire: Незарегистрированные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
import plotly.graph_objects as go
import plotly.express as px
df_scatter = show_install_top_app_interest.copy()
# Выделяем жирным шрифтом интересы, которые были в общем Топе
df_scatter['interest_name'] = df_scatter.apply(lambda row: '<b>' + row['interest_name'] + '</b>' if (row['app'] in df_bar['interest_name']) else row['interest_name'], axis=1)
df_scatter.head()
| app | interest_name | shows | installs | cr | app_name | category | |
|---|---|---|---|---|---|---|---|
| 0 | 10409400 | CrossFire: Неактивные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 1 | 10409400 | Armored Warfare: Незарегистрированные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 2 | 10409400 | Armored Warfare: Неактивные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 3 | 10409400 | ArcheAge: Незарегистрированные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
| 4 | 10409400 | CrossFire: Незарегистрированные | 11 | 11 | 1.0 | BiBi Такси | Автомобили и транспорт |
fig = px.scatter(
df_scatter, x="app_name", y="interest_name",
color="app_name",size='cr', height = 20*show_install_top_app_interest['interest_name'].nunique(),
title='Рейтинг интересов по приложениям')
fig.show()